home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dcpp / precomp.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  9KB  |  441 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  PRECOMP.C
  9.  *
  10.  *  handle precompiled includes
  11.  *
  12.  */
  13.  
  14. #include "defs.h"
  15.  
  16. #ifdef AMIGA
  17. #include "/dc1/tokens.h"
  18. #else
  19. #include "../dc1/tokens.h"
  20. #endif
  21.  
  22. #define THASHSIZE   256
  23. #define THASHMASK   (THASHSIZE-1)
  24.  
  25. #define FASTPRECOMP 1
  26.  
  27. Prototype void InitPrecomp(void);
  28. Prototype void LoadPrecompiledHeader(char *, PreCompHdr *, int);
  29. Prototype short PreCompSymbol(char *, short);
  30.  
  31. /*Prototype void DumpPrecompiledHeader(PreCompNode *, FILE *, long, long);*/
  32. Prototype void DumpPrecompiledPrefix(PreCompNode *);
  33. Prototype void DumpPrecompiledPostfix(PreCompNode *, FILE *);
  34.  
  35.  
  36. typedef struct TokenNode {
  37.     struct TokenNode *tn_Next;
  38.     char    *tn_Name;
  39.     short   tn_Len;
  40.     short   tn_Token;
  41. } TokenNode;
  42.  
  43. #define MakeToken(name,token)    { NULL, name, sizeof(name) - 1, (((token >> 4) & 0xFF00) | (ubyte)token | TOKF_PRIVATE) }
  44.  
  45. TokenNode TokenAry[] = {
  46.     MakeToken("sizeof",     TokSizeof),
  47.     MakeToken("break",      TokBreak),
  48.     MakeToken("case",       TokCase),
  49.     MakeToken("continue",   TokContinue),
  50.     MakeToken("default",    TokDefault),
  51.     MakeToken("do",         TokDo),
  52.     MakeToken("else",       TokElse),
  53.     MakeToken("for",        TokFor),
  54.     MakeToken("goto",       TokGoto),
  55.     MakeToken("if",         TokIf),
  56.     MakeToken("return",     TokReturn),
  57.     MakeToken("struct",     TokStruct),
  58.     MakeToken("enum",       TokEnum),
  59.     MakeToken("switch",     TokSwitch),
  60.     MakeToken("union",      TokUnion),
  61.     MakeToken("while",      TokWhile),
  62.     MakeToken("typedef",    TokTypeDef)
  63. };
  64.  
  65. TokenNode *TokenHash[THASHSIZE];
  66.  
  67. /*char CharType[256];*/
  68.  
  69. void
  70. InitPrecomp()
  71. {
  72.     TokenNode *tn;
  73.     TokenNode **tp;
  74.  
  75.     for (tn = TokenAry; tn < &TokenAry[arysize(TokenAry)]; ++tn) {
  76.     tp = &TokenHash[hash(tn->tn_Name, tn->tn_Len) & THASHMASK];
  77.     tn->tn_Next = *tp;
  78.     *tp = tn;
  79.     }
  80. }
  81.  
  82. short
  83. PreCompSymbol(char *ptr, short len)
  84. {
  85.     TokenNode *tn;
  86.  
  87.     for (tn = TokenHash[hash(ptr, len) & THASHMASK]; tn; tn = tn->tn_Next) {
  88.     /*fprintf(stderr, "%d %d %.*s %.*s\n", len, tn->tn_Len, len, ptr, tn->tn_Len, tn->tn_Name);*/
  89.     if (len == tn->tn_Len && cmpmem(tn->tn_Name, ptr, len) == 0) {
  90.         return(tn->tn_Token);
  91.     }
  92.     }
  93.     return(0);
  94. }
  95.  
  96. /*
  97.  *  Load precompiled header from file descriptor / specified device.
  98.  *  copy preprocessed data directly to Fo and incorporate symbol table
  99.  *  additions.
  100.  */
  101.  
  102. void
  103. LoadPrecompiledHeader(fileName, pch, fd)
  104. char *fileName;
  105. PreCompHdr *pch;
  106. int fd;
  107. {
  108.     /*
  109.      *    copy preprocessor dump
  110.      */
  111.  
  112.     if (pch->pc_CppSize) {
  113.     long bufsiz = ((pch->pc_CppSize > 32768) ? 32768 : pch->pc_CppSize);
  114.     char *buf;
  115. #if !FASTPRECOMP
  116.     long bytes = pch->pc_CppSize;
  117. #endif
  118.  
  119.     if ((buf = malloc(bufsiz)) == NULL)
  120.         ErrorNoMemory();
  121. #if FASTPRECOMP
  122.     fprintf(Fo, "#precomp %ld %ld \"%s\"\n", (long)lseek(fd, 0, 1), pch->pc_CppSize, fileName);
  123.     lseek(fd, pch->pc_CppSize, 1);
  124. #else
  125.     xxx;
  126.     bytes -= 4;    /*  don't embed \0's    */
  127.     while (bytes) {
  128.         long n;
  129.  
  130.         n = read(fd, buf, ((bytes > bufsiz) ? bufsiz : bytes));
  131.         if (n < 0)
  132.         cerror(EFATAL_READ_PRECOMP);
  133.         fwrite(buf, n, 1, Fo);
  134.         bytes -= n;
  135.     }
  136.     free(buf);
  137. #endif
  138.     }
  139.  
  140.     /*
  141.      *    incorporate symbol set    pc_SymSize
  142.      *
  143.      *    scan symbols in reverse
  144.      */
  145.  
  146.     if (pch->pc_SymSize) {
  147.     char *symData;
  148.     long i;
  149.     long j;
  150.  
  151.     if ((symData = malloc(pch->pc_SymSize)) == NULL)
  152.         ErrorNoMemory();
  153.     if (read(fd, symData, pch->pc_SymSize) != pch->pc_SymSize)
  154.         cerror(EFATAL_PARSE_PRECOMP);
  155.     for (i = pch->pc_SymSize - 4; i > 0; i = j - 8) {
  156.         j = i - *(long *)(symData + i);
  157.         DefinePrecompSymbol((Sym *)(symData + j));
  158.     }
  159.     }
  160. }
  161.  
  162. /*
  163.  *  Dump prefix and postfix for preprocessed headers
  164.  */
  165.  
  166. void
  167. DumpPrecompiledPrefix(pcn)
  168. PreCompNode *pcn;
  169. {
  170.     PreCompHdr pch;
  171.  
  172.     /*
  173.      *    dummy header
  174.      */
  175.  
  176.     pch.pc_Magic = 0;        /*    bad value for now   */
  177.     pch.pc_SymSize = 0;
  178.     pch.pc_CppSize = 0;
  179.     pch.pc_Version[0] = 0;
  180.     fwrite(&pch, 1, sizeof(pch), Fo);
  181.     fputc('\n', Fo);        /*  need an initial newline */
  182. }
  183.  
  184. /*
  185.  *  Dump Postfix for precompiled headers
  186.  *
  187.  *  Note that foOrig is our cpp output file, NOT the precompiled output
  188.  *  file (which is still Fo)
  189.  */
  190.  
  191. void
  192. DumpPrecompiledPostfix(pcn, foOrig)
  193. PreCompNode *pcn;
  194. FILE *foOrig;
  195. {
  196.     PreCompHdr pch;
  197.     long pos1;
  198.     long pos2;
  199.  
  200.     fwrite("\0\0\0\0", 4, 1, Fo);   /* terminator for DC1   */
  201.     pos1 = ftell(Fo);
  202.     DumpPrecompSymbols(Fo);
  203.     pos2 = ftell(Fo);
  204.  
  205.     /*
  206.      *    fixup header
  207.      */
  208.  
  209.     fseek(Fo, 0L, 0);
  210.     pch.pc_Magic = PCH_MAGIC;
  211.     pch.pc_SymSize = pos2 - pos1;
  212.     pch.pc_CppSize = pos1 - sizeof(pch);
  213.     strcpy(pch.pc_Version, VersionId);
  214.     fwrite(&pch, sizeof(pch), 1, Fo);
  215.  
  216. #if FASTPRECOMP
  217.     fprintf(foOrig, "#precomp %d %ld \"%s\"\n",
  218.     sizeof(pch),
  219.     pch.pc_CppSize,
  220.     pcn->pn_OutName
  221.     );
  222. #else
  223.     {
  224.     static char XBuf[2048];
  225.     long n;
  226.     long s;
  227.  
  228.     for (s = pch.pc_CppSize; s; s -= n) {
  229.         n = (s < sizeof(XBuf)) ? s : sizeof(XBuf);
  230.         if (fread(XBuf, 1, n, Fo) == n) {
  231.         if (fwrite(XBuf, 1, n, foOrig) != n) {
  232.             exit(22);
  233.         }
  234.         } else {
  235.         exit(22);
  236.         }
  237.     }
  238.     }
  239. #endif
  240. }
  241.  
  242. /*
  243.  *  Save preprocessed header from fo<begpos-endpos> to pcn->pn_OutName,
  244.  *  also save symbol table
  245.  */
  246.  
  247. #ifdef NOTDEF3
  248.  
  249. void
  250. DumpPrecompiledHeader(pcn, fi, begpos, endpos)
  251. PreCompNode *pcn;
  252. FILE *fi;
  253. long begpos;
  254. long endpos;
  255. {
  256.     PreCompHdr pch;
  257.     FILE *fo;
  258.     long pos;
  259.     static char *SymRefPtr[256];
  260.     static long SymRefLen[256];
  261. #ifdef NOTDEF
  262.     short symRefIdx = 0;
  263. #endif
  264.  
  265.     setmem(SymRefLen, sizeof(SymRefLen), 0);
  266.     if ((fo = fopen(pcn->pn_OutName, "w+")) == NULL)
  267.     cerror(EFATAL_CANT_CREATE_FILE, pcn->pn_OutName);
  268.     if (fseek(fi, begpos, 0) < 0)
  269.     cerror(EFATAL_SEEK_PRECOMP);
  270.  
  271.     /*
  272.      *    dummy header
  273.      */
  274.  
  275.     pch.pc_Magic = 0;        /*    bad value for now   */
  276.     pch.pc_SymSize = 0;
  277.     pch.pc_CppSize = 0;
  278.     pch.pc_Version[0] = 0;
  279.     fwrite(&pch, 1, sizeof(pch), fo);
  280.  
  281.     /*
  282.      *    copy preprocessor dump to precomp file, tokenize simple constructs
  283.      */
  284.  
  285.     if (endpos != begpos) {
  286.     char *buf;
  287.     long bytes = endpos - begpos;
  288.     long j = 0;
  289.     short c;
  290.     short wsFlag = 0;   /*    remove white space flag */
  291.  
  292.     if ((buf = malloc(bytes)) == NULL)
  293.         ErrorNoMemory();
  294.     if (fread(buf, bytes, 1, fi) != 1)
  295.         cerror(EFATAL_READ_PRECOMP);
  296.  
  297.     pch.pc_CppSize = bytes;
  298.  
  299.     fwrite(buf, bytes, 1, fo);
  300.  
  301. #ifdef NOTDEF2        /*    doesn't help enough */
  302.     while (j < bytes) {
  303.         long i;
  304.  
  305.         c = buf[j];
  306.  
  307.         /*
  308.          *    Scan for symbols.  Ignore symbols that are part of numbers
  309.          *    because DC1 cannot parse that.    We must also ignore
  310.          *    quoted strings and character constants.
  311.          */
  312.  
  313.         switch(CharType[c]) {
  314.         case -2:     /* white space         */
  315.         if (wsFlag) {
  316.             --pch.pc_CppSize;
  317.         } else {
  318.             putc(c, fo);
  319.             wsFlag = 1;
  320.         }
  321.         ++j;
  322.         continue;
  323.         case -1:     /* quote or single quote   */
  324.         wsFlag = 0;
  325.         for (i = j, ++j; j < bytes && buf[j] != buf[i]; ++j) {
  326.             if (buf[j] == '\\')
  327.             ++j;
  328.         }
  329.         ++j;
  330.         fwrite(buf + i, j - i, 1, fo);
  331.         break;
  332.         case 0:    /*  not anything remarkable */
  333.         wsFlag = 0;
  334.         putc(c, fo);
  335.         ++j;
  336.         break;
  337.         case 3:
  338.         for (i = j, ++j; j < bytes && buf[j] != '\n'; ++j)
  339.             ;
  340.         fwrite(buf + i, j - i, 1, fo);
  341.         break;
  342.         case 1:    /*  number            */
  343.         /*
  344.          *  In parsing a number we skip potential symbols embedded
  345.          *  in the number because DC1 cannot handle this case.
  346.          */
  347.  
  348.         wsFlag = 0;
  349.         for (i = j, ++j; j < bytes && (CharType[c = buf[j]] > 0 || c == '.'); ++j)
  350.             ;
  351.         fwrite(buf + i, j - i, 1, fo);
  352.         break;
  353.         case 2:    /*  symbol            */
  354.         /*
  355.          *  In parsing a symbol note that numerical types are valid
  356.          *  symbol characters after the first character, e.g. A23
  357.          */
  358.  
  359.         wsFlag = 0;
  360.         {
  361.             TokenNode *tn;
  362.             char *ptr = buf + j;
  363.  
  364.             for (i = j, ++j; j < bytes && CharType[buf[j]] > 0; ++j)
  365.             ;
  366.             i = j - i;        /*    i == length of symbol    */
  367.  
  368.             for (tn = TokenHash[hash(ptr, i) & THASHMASK]; tn; tn = tn->tn_Next) {
  369.             if (tn->tn_Len == i && cmpmem(ptr, tn->tn_Name, i) == 0)
  370.                 break;
  371.             }
  372.             if (tn) {
  373.             fwrite(&tn->tn_Token, sizeof(tn->tn_Token), 1, fo);
  374.             pch.pc_CppSize -= i - sizeof(tn->tn_Token);
  375.             wsFlag = 1;
  376.             } else {
  377. #ifdef NOTDEF
  378.             short idx;
  379.  
  380.             /*
  381.              *  check previously used symbols.  When placing
  382.              *  a reference use a simple 8 bit hash value but
  383.              *  leave room to allow DC1 to change it to a
  384.              *  real pointer.
  385.              */
  386.  
  387.             for (idx = (symRefIdx - 1) & 255; idx != symRefIdx; idx = (idx - 1) & 255) {
  388.                 if (i == SymRefLen[idx] && cmpmem(SymRefPtr[idx], ptr, i) == 0)
  389.                 break;
  390.             }
  391.             idx = (symRefIdx - idx) & 255;
  392.  
  393.             if (idx > 0 && idx < 128) {
  394.                 putc(TokCppRef1_Byte, fo);
  395.                 putc(idx, fo);
  396.                 pch.pc_CppSize -= i - sizeof(tn->tn_Token);
  397.                 wsFlag = 1;
  398.             } else
  399. #endif
  400.             {
  401. #ifdef NOTDEF
  402.                 SymRefPtr[symRefIdx] = ptr;
  403.                 SymRefLen[symRefIdx] = i;
  404.                 symRefIdx = (symRefIdx + 1) & 0xFF;
  405. #endif
  406.                 fwrite(ptr, i, 1, fo);
  407.                 wsFlag = 0;
  408.             }
  409.             }
  410.         }
  411.         break;
  412.         }
  413.     }
  414. #endif
  415.     free(buf);
  416.     }
  417.  
  418.     fseek(fo, 0L, 1);
  419.     pos = ftell(fo);
  420.  
  421.     /*
  422.      *    dump symbols
  423.      */
  424.  
  425.     DumpPrecompSymbols(fo);
  426.  
  427.     /*
  428.      *    fixup header
  429.      */
  430.  
  431.     pch.pc_Magic = PCH_MAGIC;
  432.     pch.pc_SymSize = ftell(fo) - pos;
  433.     strcpy(pch.pc_Version, VersionId);
  434.     fseek(fo, 0L, 0);
  435.     fwrite(&pch, sizeof(pch), 1, fo);
  436.     fclose(fo);
  437.     fseek(fi, endpos, 0);
  438. }
  439.  
  440. #endif
  441.